﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using OS_PROJECT;
using System.Threading;

namespace operatingsystem
{
    public partial class ospanel : Form
    {
        public static ospanel form;
        Driver kernel;
  

        public ospanel()
        {
            InitializeComponent();
            form = this;
           
        }



        public delegate void RefreshDelegate(uint i);

        private void loadJob_Click(object sender, EventArgs e)
        {
            OpenFileDialog o = new OpenFileDialog();
            o.Filter = "文本文件(*.txt)|";

            if (o.ShowDialog() == DialogResult.OK && File.Exists(o.FileName))
            {
                MessageBox.Show(o.FileName);
                kernel = new Driver(o.FileName);
                new Thread(new ThreadStart(kernel.RunOS)).Start();

                kernel.loader.refreshCount = new Loader.RefreshBatCountDelegate(setBatchcount);
                kernel.LTS.refreshCount = new LongTermScheduler.RefreshBatCountDelegate(setBatchcount);
                kernel.LTS.RQrefresh = new LongTermScheduler.RQrefreshDelegate(setRQlist);

                kernel.loader.refreshNPQ = new Loader.RefreshNPQDelegate(setNPQlist);
                kernel.Dispatcher.RefreshRQ = new Dispatcher.RefreshRQDelegate(refreshRQandCPUinfo);

                InterruptHandler.refreshBlocklist = new InterruptHandler.blocklistDelegate(refreshBlocklist);


                foreach (CPU cpu in kernel.cpuList) {

                    cpu.refreshCpuTrue += new CPU.CpuDelegete(setCpuAwaking);
                    cpu.refreshCpuFalse += new CPU.CpuDelegete(setCpuSleep);

                    cpu.refreshFinish += new CPU.finishDelegate(setFinishlist);

                    cpu.refreshCpuStatus = new CPU.cpuStatusDelegate(setCpuProcessing);

                }
                timer1.Start();

            }
            o.Dispose();
        }

        private void listBox3_SelectedIndexChanged(object sender, EventArgs e)
        {

        }



        private void setCpuSleep(int id) {






            switch (id)
            {


                case 0:
                    {


                        if (this.cpu0.InvokeRequired)
                        {

                            this.Invoke(kernel.cpuList.ElementAt<CPU>(0).refreshCpuFalse, new object[] { id });
                        }
                        else
                        {
                            ospanel.form.cpu0.Checked = false;
                            cpu0_status.Text = "休眠";
                            
                            break;
                           
                        }



                    }

                    break;
                case 1:
                    {


                        if (this.cpu1.InvokeRequired)
                        {

                            this.Invoke(kernel.cpuList.ElementAt<CPU>(1).refreshCpuFalse, new object[] { id });
                        }
                        else
                        {
                            ospanel.form.cpu1.Checked = false; cpu1_status.Text = "休眠"; break;
                        }



                    }

                    break;
                case 2:
                    {


                        if (this.cpu2.InvokeRequired)
                        {

                            this.Invoke(kernel.cpuList.ElementAt<CPU>(2).refreshCpuFalse, new object[] { id });
                        }
                        else
                        {
                            ospanel.form.cpu2.Checked = false; cpu2_status.Text = "休眠"; break;
                        }



                    }

                    break;
                case 3:
                    {


                        if (this.cpu3.InvokeRequired)
                        {

                            this.Invoke(kernel.cpuList.ElementAt<CPU>(3).refreshCpuFalse, new object[] { id });
                        }
                        else
                        {
                            ospanel.form.cpu3.Checked = false; cpu3_status.Text = "休眠"; break;
                        }



                    }

                    break;
            }

            
        
        
        
        
        }




        private void setCpuProcessing(CPU cpu,string statusString) {


            switch (cpu.id)
            {


                case 0:
                    {


                        if (this.cpu0.InvokeRequired)
                        {

                            this.Invoke(kernel.cpuList.ElementAt<CPU>(0).refreshCpuStatus, new object[] { cpu,statusString});
                        }
                        else
                        {
                            cpu0_status.Text = statusString; break;
                        }



                    }

                    break;
                case 1:
                    {


                        if (this.cpu1.InvokeRequired)
                        {

                            this.Invoke(kernel.cpuList.ElementAt<CPU>(1).refreshCpuStatus, new object[] { cpu, statusString });
                        }
                        else
                        {
                            cpu1_status.Text = statusString; break;
                        }



                    }

                    break;
                case 2:
                    {


                        if (this.cpu2.InvokeRequired)
                        {

                            this.Invoke(kernel.cpuList.ElementAt<CPU>(2).refreshCpuStatus, new object[] { cpu, statusString });
                        }
                        else
                        {
                            cpu2_status.Text = statusString; break;
                        }



                    }

                    break;
                case 3:
                    {


                        if (this.cpu3.InvokeRequired)
                        {

                            this.Invoke(kernel.cpuList.ElementAt<CPU>(3).refreshCpuStatus, new object[] { cpu, statusString });
                        }
                        else
                        {
                            cpu3_status.Text = statusString; break;
                        }



                    }

                    break;
            }
        
        
        
        }




        private void setCpuAwaking(int id)
        {

           
                switch (id)
                {


                    case 0:
                        {


                            if (this.cpu0.InvokeRequired)
                            {

                                this.Invoke(kernel.cpuList.ElementAt<CPU>(0).refreshCpuTrue, new object[] { id });
                            }
                            else
                            {
                                ospanel.form.cpu0.Checked = true; cpu0_status.Text = "激活"; break;
                            }  

                        
                        
                        }

                        break;
                    case 1:
                            {


                            if (this.cpu1.InvokeRequired)
                            {

                                this.Invoke(kernel.cpuList.ElementAt<CPU>(1).refreshCpuTrue, new object[] { id });
                            }
                            else
                            {
                                ospanel.form.cpu1.Checked = true; cpu1_status.Text = "激活";break;
                            }  

                        
                        
                        }

                        break;
                    case 2:
                             {


                            if (this.cpu2.InvokeRequired)
                            {

                                this.Invoke(kernel.cpuList.ElementAt<CPU>(2).refreshCpuTrue, new object[] { id });
                            }
                            else
                            {
                                ospanel.form.cpu2.Checked = true; cpu2_status.Text = "激活"; break;
                            }  

                        
                        
                        }

                        break;
                    case 3:
                            {


                            if (this.cpu3.InvokeRequired)
                            {

                                this.Invoke(kernel.cpuList.ElementAt<CPU>(3).refreshCpuTrue, new object[] { id });
                            }
                            else
                            {
                                ospanel.form.cpu3.Checked = true; cpu3_status.Text = "激活";break;
                            }  

                        
                        
                        }

                        break;
                }

            


        }

        private void setBatchcount(uint i)
        {

            //判断该方法是否被主线程调用，也就是创建labMessage1控件的线程，当控件的InvokeRequired属性为ture时，说明是被主线程以外的线程调用。如果不加判断，会造成异常  
            if (this.batchcountnum.InvokeRequired)
            {
               
                this.Invoke(kernel.loader.refreshCount, new object[] { i });
            }
            else
            {
                batchcountnum.Text = i.ToString();
            }  

           



        }



        private void setRamprogress() {

            int nofree = 0;

            for (uint iterator = 0; iterator < 256; iterator++)
            {
                if (!MMU.FrameTable[iterator].IsFree) {

                    nofree++;
                
                
                };
             
            }


            ramprogressBar.Value = (int)(nofree*100 / 256);

        
        
        
        
        }

        private void setRQlist(Process p) {

            if (this.RQlist.InvokeRequired)
            {

                this.Invoke(kernel.LTS.RQrefresh, new object[] { p });
            }
            else
            {
                RQlist.Items.Add("进程ID" + p.PCB.ProcessID + " 地址" + p.PCB.DiskAddress + " 优先" + p.PCB.Priority + " 长度" + p.PCB.InstructionLength);
              
            }  
        
        
        }



        private void setFinishlist(CPU cpu)
        {
            if (this.finishlist.InvokeRequired)
            {

                this.Invoke(kernel.cpuList.ElementAt<CPU>(0).refreshFinish, new object[] {cpu});
            }
            else
            {
                finishlist.Items.Add("进程 " + cpu.cpuPCB.ProcessID + " 使用了 " + cpu.cpuPCB.IoCount + " 次I/O ");
                 finishlist.Items.Add("处理cpu: " + cpu.id + " "+"消耗时间 " + cpu.totalElapsedTime.Elapsed.TotalMilliseconds.ToString() + "毫秒");
            }

        }


        private void setNPQlist(Process p)
        {
            if (this.npqlist.InvokeRequired)
            {

                this.Invoke(kernel.loader.refreshNPQ, new object[] { p });
            }
            else
            {
                npqlist.Items.Add("进程ID" + p.PCB.ProcessID + " 地址" + p.PCB.DiskAddress + " 优先" + p.PCB.Priority+" 长度"+p.PCB.InstructionLength);
            }  
        
        }



        private void refreshRQandCPUinfo(CPU cpu)
        {


            switch (cpu.id) {


                case 0:
                    {
                        if (this.InvokeRequired)
                        {

                            this.Invoke(kernel.Dispatcher.RefreshRQ, new object[] { cpu });
                        }
                        else
                        {
                            cpu0_pid.Text = cpu.CPU_PCB.ProcessID.ToString();
                            cpu0_ilen.Text = cpu.CPU_PCB.InstructionLength.ToString();
                            cpu0_priority.Text = cpu.CPU_PCB.Priority.ToString();
                            cpu0_waittime.Text = cpu.CPU_PCB._waitingTime.Elapsed.TotalMilliseconds.ToString() + "ms";
                           RQlist.Items.RemoveAt(0);
                               
                        }
                    }
                    break;
                case 1:
                    {
                        if (this.InvokeRequired)
                        {

                            this.Invoke(kernel.Dispatcher.RefreshRQ, new object[] { cpu });
                        }
                        else
                        {
                            cpu1_pid.Text = cpu.CPU_PCB.ProcessID.ToString();
                            cpu1_ilen.Text = cpu.CPU_PCB.InstructionLength.ToString();
                            cpu1_priority.Text = cpu.CPU_PCB.Priority.ToString();
                            cpu1_waittime.Text = cpu.CPU_PCB._waitingTime.Elapsed.TotalMilliseconds.ToString() + "ms";
                            RQlist.Items.RemoveAt(0);
                        }
                    }
                    break;
                case 2:
                    {
                        if (this.InvokeRequired)
                        {

                            this.Invoke(kernel.Dispatcher.RefreshRQ, new object[] { cpu });
                        }
                        else
                        {
                            cpu2_pid.Text = cpu.CPU_PCB.ProcessID.ToString();
                            cpu3_ilen.Text = cpu.CPU_PCB.InstructionLength.ToString();
                            cpu2_priority.Text = cpu.CPU_PCB.Priority.ToString();
                            cpu2_waittime.Text = cpu.CPU_PCB._waitingTime.Elapsed.TotalMilliseconds.ToString() + "ms";
                            RQlist.Items.RemoveAt(0);
                        }
                    } 
                    break;
                case 3:
                    {
                        if (this.InvokeRequired)
                        {

                            this.Invoke(kernel.Dispatcher.RefreshRQ, new object[] { cpu });
                        }
                        else
                        {
                            cpu3_pid.Text = cpu.CPU_PCB.ProcessID.ToString();
                            cpu3_ilen.Text = cpu.CPU_PCB.InstructionLength.ToString();
                            cpu3_priority.Text = cpu.CPU_PCB.Priority.ToString();
                            cpu3_waittime.Text = cpu.CPU_PCB._waitingTime.Elapsed.TotalMilliseconds.ToString() + "ms";
                           RQlist.Items.RemoveAt(0);
                        }
                    } 
                    break;
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            }








        }

        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            LongTermScheduler.schedulerScheme = "Priority";

        }

        private void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            LongTermScheduler.schedulerScheme = "SJF";

        }

        private void radioButton3_CheckedChanged(object sender, EventArgs e)
        {
            LongTermScheduler.schedulerScheme = "FCFS";

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            setRamprogress();
        }


        private void refreshBlocklist(Process p,Boolean isRemove,uint page) {



            if (blocklist.InvokeRequired)
            {

                this.Invoke(InterruptHandler.refreshBlocklist, new object[] { p,isRemove,page });
            }

            else
            {

                if (isRemove)
                {

                    blocklist.Items.RemoveAt(0);
                }


                else
                {

                    blocklist.Items.Add("阻塞进程ID"+p.PCB.ProcessID +" "+"第"+page+"页面请求阻塞");

                }

            }
        
        
        
        }

        private void button2_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFile = new SaveFileDialog();
            saveFile.Filter = "文本|*.txt";
            if (saveFile.ShowDialog() == DialogResult.OK) {


                SystemCaller.DiskDump(kernel, saveFile.FileName);
            
            
            
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFile = new SaveFileDialog();
            saveFile.Filter = "文本|*.txt";
            if (saveFile.ShowDialog() == DialogResult.OK)
            {


                SystemCaller.ProcessCmpltWaitTimesDump(kernel, saveFile.FileName);



            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFile = new SaveFileDialog();
            saveFile.Filter = "文本|*.txt";
            if (saveFile.ShowDialog() == DialogResult.OK)
            {


                SystemCaller.CoreDump(kernel, saveFile.FileName);



            }
        }

       
    }
}
